gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scwinlib/SCBitmap.cpp

    //Download by http://www.NewXing.com
/*
*	This file is part of the EMFexplorer projet.
*	Copyright (C) 2004 Smith Charles.
*
*	This library is free software; you can redistribute it and/or
*	modify it under the terms of the GNU Lesser General Public
*	License as published by the Free Software Foundation; either
*	version 2.1 of the License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with this library; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
*
*	Extension: for commercial use, apply the Equity Public License, which
*	adds to the normal terms of the GLPL a condition of donation to the author.
*   If you are interested in support for this source code,
*   contact Smith Charles <smith.charles@free.fr> for more information.
*/


#include "stdafx.h"
#include "SCBitmap.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Create a n-bit-per-pixel surface.
HBITMAP SCCreateDIBSection(HDC hDC, int iWidth, int iHeight, int iBitCount)
{
	BITMAPINFO bmi;
	HBITMAP hbm;
	LPVOID pBits;
	
	// Initialize to 0s.
	ZeroMemory(&bmi, sizeof(bmi));
	
	// Initialize the header.
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = iWidth;
	bmi.bmiHeader.biHeight = iHeight; //warning: bottom-up bitmap
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = iBitCount;
	bmi.bmiHeader.biCompression = BI_RGB;
	
	// Create the surface.
	if (hDC)
		hbm = ::CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
	else
	{// use the screen
		HDC hSrcndc = ::GetDC(NULL);
		hbm = ::CreateDIBSection(hSrcndc, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
		::ReleaseDC(NULL, hSrcndc);
	}

	return(hbm);
}

// Create a grayscale surface.
HBITMAP SCCreateGrayScaleDIBSection(HDC hDC, int iWidth, int iHeight, int nBits/* = 8*/)
{
	BITMAPINFO* pbmi=NULL;
	HBITMAP hbm;
	LPVOID pBits;

	HDC    hRefDC;
	DWORD dwSize = sizeof(BITMAPINFO);
	UINT uEntries;

	switch (nBits)
	{
	case 2:
		uEntries = 4;
		break;

	case 4:
		uEntries = 16;
		break;

	case 8:
		uEntries = 256;
		break;

	default:
		return NULL;
	}

	hRefDC = GetDC( NULL );
	if(hRefDC)
	{
		//SetStretchBltMode(hRefDC, HALFTONE);
	} else
		return NULL;

	
	// Create the logical palette based on the entries
	// Allocate memory for the palette.
	dwSize += uEntries*sizeof(PALETTEENTRY);
	pbmi = (BITMAPINFO*) new BYTE[dwSize];
	if (!pbmi)
	{
		ReleaseDC( NULL, hRefDC );
		return NULL;
	}
	// Initialize to 0s.
	ZeroMemory(pbmi, dwSize);
	LPPALETTEENTRY pPal = (LPPALETTEENTRY)&pbmi->bmiColors;
	// gray scale palette
	for (int i=0;(UINT)i<uEntries;i++)
	{
		pPal->peRed = pPal->peGreen = pPal->peBlue = (BYTE)(i & 0xFF);
		pPal->peFlags  = 0;
		pPal++;
	}
	
	// Finish Initialize header.
	pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	pbmi->bmiHeader.biWidth = iWidth;
	pbmi->bmiHeader.biHeight = iHeight; //warning: bottom-up bitmap
	pbmi->bmiHeader.biPlanes = 1;
	pbmi->bmiHeader.biBitCount = nBits;
	pbmi->bmiHeader.biCompression = BI_RGB;
	//pbmi->bmiHeader.biClrUsed = uEntries;
	
	// Create the surface.
	if (hDC)
		hbm = ::CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);
	else
	// use the screen
		hbm = ::CreateDIBSection(hRefDC, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0);

	delete [] pbmi;
	ReleaseDC( NULL, hRefDC );
	return(hbm);
}

//Just extract the non-white block
//The transparent color is white
BYTE *SCExtractMemBoundingBox(BYTE *lpmem, LPRECT pR, DWORD dwSize, long sScanBytes, short sBitPel)
{
	BYTE *lpTop = lpmem;
	BYTE *lpBottom = lpTop + dwSize;
	BYTE *lpTmp;
	ASSERT(lpmem && pR && dwSize && sScanBytes && sBitPel);
	if ( (!lpmem) || (!pR)|| (!dwSize) || (!sScanBytes) || (!sBitPel))
		return NULL;

	long widthBytes = ((pR->right - pR->left)*(0L+sBitPel))/8;
	ASSERT(widthBytes<=sScanBytes);
	// top band
	lpTmp = lpTop;
	long top;
	while ((lpTop<lpBottom) && (0xFF == *lpTop))
	{
		lpTop++;
		if (lpTop - lpTmp>=widthBytes)
		{// skip extra bytes
			lpTmp += sScanBytes;
			lpTop = lpTmp;
		}
	}
	// check full blank page
	if (lpTop>=lpBottom)
	{
		// blank page
		::SetRectEmpty(pR);
		return lpBottom;
	}
	top = (long)((lpTop - lpmem) / sScanBytes);	// line where drawing begins
	lpTop = lpmem + (top+0L) * sScanBytes;		// adjust to first byte on scan line

	// bottom band
	lpTmp = lpBottom - sScanBytes;
	BYTE *lpRight = lpTmp + widthBytes;
	BOOL bOkB = FALSE;
	long bottom;
	while (lpTmp>lpTop)
	{
		lpBottom = lpTmp;
		// check this scan line, up to extra bytes
		while (lpBottom<lpRight)
		{ 
			if (0xFF != *lpBottom)
			{
				bOkB = TRUE;
				break;
			}
			lpBottom++;
		}
		if (bOkB)
			break;

		// go up one scan line
		lpTmp -= sScanBytes;
		lpRight -= sScanBytes;
	}

	bottom = (long)((lpBottom - lpmem) / sScanBytes);	// after line where drawing ends
	lpBottom = lpmem + (bottom+0L) * sScanBytes;		// adjust to first byte on next scan line

	// left band (scan one column at a time)
	BOOL bOkL = FALSE;
	long left=-1;
	while(left<widthBytes)
	{
		lpTmp = lpTop + (++left);
		while (lpTmp<lpBottom)
		{
			if(0xFF != *lpTmp)
			{
				bOkL = TRUE;
				pR->left=(int)((LONG)left*8) / sBitPel;
				break;
			}
			lpTmp += sScanBytes;
		}
		if (bOkL)
			break;
	}

	// right band
	BOOL bOkR = FALSE;
	long right=widthBytes;
	while (right>left)
	{
		lpTmp = lpTop + (--right);
		while (lpTmp<lpBottom)
		{
			if(0xFF != *lpTmp)
			{
				bOkR = TRUE;
				pR->right=(int)((LONG)right*8L) / sBitPel;
				break;
			}
			lpTmp += sScanBytes;
		}
		if (bOkR)
			break;
	}

	// transform left and right in pixels
	pR->top=top;
	pR->bottom=bottom;
	return lpBottom;
}


///
/// Make a copy of a GDI logical palette
///
HPALETTE SCCopyPalette (HPALETTE hpal)
{
	ASSERT(hpal);

    WORD nNumEntries;
   if (!hpal || !GetObject(hpal, sizeof(nNumEntries), &nNumEntries))
        return NULL;

    if (nNumEntries == 0)
        return NULL;

    PLOGPALETTE pPal = (PLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + nNumEntries * sizeof(PALETTEENTRY)];
    if (!pPal)
        return NULL;

    pPal->palVersion    = 0x300;
    pPal->palNumEntries = nNumEntries;

    GetPaletteEntries(hpal, 0, nNumEntries, (LPPALETTEENTRY)pPal->palPalEntry);

    hpal = CreatePalette(pPal);

	delete [] (BYTE*)pPal;
    return hpal;
}

///
/// Copy an area from a bitmap (or the whole bitmap)
///
HBITMAP SCCopyBitmap(HBITMAP hbm, HDC hdc/*=NULL*/, LPRECT prect/*=NULL*/)
{
	ASSERT(hbm);

    BITMAP  bm;
    if (!hbm || !GetObject(hbm, sizeof(bm), &bm))
	{
#ifdef _DEBUG
		DWORD dwError = GetLastError();
		//SCShowError();
#endif
		return NULL;
	}
	
	BOOL bTmpDC = (NULL==hdc);
	if (bTmpDC)
		hdc = GetDC(NULL);

	int iCx = prect ? prect->right  - prect->left : bm.bmWidth;
	int iCy = prect ? prect->bottom - prect->top : bm.bmHeight;

	HBITMAP hNewBm = CreateCompatibleBitmap(hdc, iCx, iCy);
	if (hNewBm)
	{
		HDC hMemDCsrc = CreateCompatibleDC(hdc);
		HDC hMemDCdst = CreateCompatibleDC(hdc);

		HBITMAP hOldBMSrc = (HBITMAP)SelectObject(hMemDCsrc, hbm);
		HBITMAP hOldBMDest = (HBITMAP)SelectObject(hMemDCdst, hNewBm);
				
		BitBlt(hMemDCdst, 0, 0, iCx, iCy,
			   hMemDCsrc, prect ? prect->left : 0,
					      prect ? prect->top  : 0, SRCCOPY);
		
		SelectObject(hMemDCsrc, hOldBMSrc);
		SelectObject(hMemDCdst, hOldBMDest);

		DeleteDC(hMemDCsrc);
		DeleteDC(hMemDCdst);
	}

	if (bTmpDC)
		ReleaseDC(NULL, hdc);

    return hNewBm;
}